package de.unikoblenz.west.csxpoi.server;

import java.io.PrintWriter;
import java.text.CharacterIterator;
import java.text.StringCharacterIterator;
import java.util.List;

import javax.servlet.http.HttpServletResponse;

/**
 * Writes XML documents for REST responses.
 */
public class XmlWriter {

	/**
	 * the content type and encoding for XML
	 */
	private static final String XML_CONTENT_TYPE = "application/xml; charset=\"utf-8\"";
	
	/**
	 * the XML header string
	 */
	public static final String XML_HEADER = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>";

	
	/**
	 * Writes the XML response for a collection of POIs.
	 * 
	 * @param response
	 *            the response to write to
	 * @param pois
	 *            the list of POIs to write
	 */
	public static void writePoisResponse(HttpServletResponse response,
			List<PoiWrapper> pois) {

		response.setContentType(XML_CONTENT_TYPE);
		PrintWriter writer = ServletHelper.utf8Writer(response);
		writer.println(XML_HEADER);
		writer.println(dtdLink("pois"));

		if (pois != null) {
			writer.println("<pois status=\"success\">");
			for (PoiWrapper poi : pois) {
				writer.println("\t<poi id=\"" + poi.getUri() + "\">");
				writer.println("\t\t<name>" + ServletHelper.filterSymbols(poi.getName()) + "</name>");
				writer.println("\t\t<lat>" + poi.getLatitude() + "</lat>");
				writer.println("\t\t<long>" + poi.getLongitude() + "</long>");
				writer.println("\t\t<alt>" + poi.getAltitude() + "</alt>");
//				writer.println("\t\t<type>" + ServletHelper.filterSymbols(poi.getType()) + "</type>");
				// TODO event
				writer.println("\t\t<start>" + poi.getStartDate() + "</start>");
				writer.println("\t\t<end>" + poi.getEndDate() + "</end>");
				
				writer.println("\t\t<categories>");
				for (CategoryWrapper category : poi.getCategories()) {
					writer.println("\t\t\t<category id=\"" + category.getUri()
							+ "\">");
					writer.println("\t\t\t\t<name>" + ServletHelper.filterSymbols(category.getName())
							+ "</name>");
					writer.println("\t\t\t</category>");
				}
				writer.println("\t\t</categories>");
				// writer.println("\t\t<equivalents>");
				// writer.println("\t\t</equivalents>");
				writer.println("\t</poi>");
			}
			writer.println("</pois>");
		} else {
			writer.println("<pois status=\"failure\" />");
		}
	}

	/**
	 * Writes the XML response for a single POI.
	 * 
	 * @param response
	 *            the response to write to
	 * @param poi
	 *            the POI to write
	 */
	public static void writePoiResponse(HttpServletResponse response,
			PoiWrapper poi) {

		response.setContentType(XML_CONTENT_TYPE);
		PrintWriter writer = ServletHelper.utf8Writer(response);
		writer.println(XML_HEADER);
		writer.println(dtdLink("poi"));

		if (poi != null) {
			writer.println("<poi status=\"success\">");
			writer.println("\t<id>" + poi.getUri() + "</id>");
			writer.println("\t<name>" + ServletHelper.filterSymbols(poi.getName()) + "</name>");
			writer.println("\t<lat>" + poi.getLatitude() + "</lat>");
			writer.println("\t<long>" + poi.getLongitude() + "</long>");
			writer.println("\t<alt>" + poi.getAltitude() + "</alt>");
			
			// TODO event
			writer.println("\t<start>" + poi.getStartDate() + "</start>");
			writer.println("\t<end>" + poi.getEndDate() + "</end>");
			
			writer.println("\t<categories>");
			for (CategoryWrapper category : poi.getCategories()) {
				writer.println("\t\t<category id=\"" + category.getUri()
						+ "\">");
				writer.println("\t\t\t<name>" + ServletHelper.filterSymbols(category.getName()) + "</name>");
				writer.println("\t\t</category>");
			}
			writer.println("\t</categories>");
			writer.println("\t<equivalents>");
			for (PoiWrapper equivalent : poi.getEquivalents()) {
				writer
						.println("\t\t<poi id=\"" + equivalent.getUri()
								+ "\" />");
			}
			writer.println("\t</equivalents>");
			writer.println("</poi>");
		} else {
			writer.println("<poi status=\"failure\" />");
		}
	}

	/**
	 * Writes the XML response for a collection of categories.
	 * 
	 * @param response
	 *            the response to write to
	 * @param categories
	 *            the list of categories to write
	 */
	public static void writeCategoriesResponse(HttpServletResponse response,
			List<CategoryWrapper> categories) {

		response.setContentType(XML_CONTENT_TYPE);
		PrintWriter writer = ServletHelper.utf8Writer(response);
		writer.println(XML_HEADER);
		writer.println(dtdLink("categories"));

		if (categories != null) {
			writer.println("<categories status=\"success\">");
			for (CategoryWrapper category : categories) {
				writer.println("\t<category id=\"" + category.getUri() + "\">");
				writer.println("\t\t<name>" + ServletHelper.filterSymbols(category.getName()) + "</name>");
				// writer.println("\t\t<subclasses>");
				// writer.println("\t\t</subclasses>");
				// writer.println("\t\t<superclasses>");
				// writer.println("\t\t</superclasses>");
				// writer.println("\t\t<equivalents>");
				// writer.println("\t\t</equivalents>");
				writer.println("\t</category>");
			}
			writer.println("</categories>");
		} else {
			writer.println("<categories status=\"failure\" />");
		}
	}

	/**
	 * Writes the XML response for a single category.
	 * 
	 * @param response
	 *            the response to write to
	 * @param category
	 *            the category to write
	 */
	public static void writeCategoryResponse(HttpServletResponse response,
			CategoryWrapper category) {

		response.setContentType(XML_CONTENT_TYPE);
		PrintWriter writer = ServletHelper.utf8Writer(response);
		writer.println(XML_HEADER);
		writer.println(dtdLink("category"));

		if (category != null) {
			writer.println("<category status=\"success\">");
			writer.println("\t<id>" + category.getUri() + "</id>");
			writer.println("\t<name>" + ServletHelper.filterSymbols(category.getName()) + "</name>");
			writer.println("\t<subclasses>");
			for (CategoryWrapper subclass : category.getSubclasses()) {
				writer.println("\t\t<subclass id=\"" + subclass.getUri()
						+ "\">");
				writer.println("\t\t\t<name>" + ServletHelper.filterSymbols(subclass.getName()) + "</name>");
				writer.println("\t\t</subclass>");
			}
			writer.println("\t</subclasses>");
			writer.println("\t<superclasses>");
			for (CategoryWrapper superclass : category.getSuperclasses()) {
				writer.println("\t\t<superclass id=\"" + superclass.getUri()
						+ "\">");
				writer.println("\t\t\t<name>" + ServletHelper.filterSymbols(superclass.getName())
						+ "</name>");
				writer.println("\t\t</superclass>");
			}
			writer.println("\t</superclasses>");
			writer.println("\t<equivalents>");
			for (CategoryWrapper equivalent : category.getEquivalents()) {
				writer.println("\t\t<equivalent id=\"" + equivalent.getUri()
						+ "\">");
				writer.println("\t\t\t<name>" + ServletHelper.filterSymbols(equivalent.getName())
						+ "</name>");
				writer.println("\t\t</equivalent>");
			}
			writer.println("\t</equivalents>");
			writer.println("</category>");
		} else {
			writer.println("<category status=\"failure\" />");
		}
	}

	/**
	 * Writes the XML response for a single user.
	 * 
	 * @param response
	 *            the response to write to
	 * @param user
	 *            the user to write
	 */
	public static void writeUserResponse(HttpServletResponse response,
			UserWrapper user) {

		response.setContentType(XML_CONTENT_TYPE);
		PrintWriter writer = ServletHelper.utf8Writer(response);
		writer.println(XML_HEADER);
		writer.println(dtdLink("user"));

		if (user != null) {
			writer.println("<user status=\"success\">");
			writer.println("\t<id>" + user.getUri() + "</id>");
			writer.println("\t<username>" + ServletHelper.filterSymbols(user.getUsername()) + "</username>");
			if (user.getName() != null)
				writer.println("\t<name>" + ServletHelper.filterSymbols(user.getName()) + "</name>");
			if (user.getEmail() != null)
				writer.println("\t<email>" +  ServletHelper.filterSymbols(user.getEmail()) + "</email>");
			writer.println("</user>");
		} else {
			writer.println("<user status=\"failure\" />");
		}
	}

	/**
	 * Generates the XML DTD link for the specified name.
	 * 
	 * @param name
	 *            the name for which to generate the XML DTD link
	 * @return the XML DTD link for the specified name
	 */
	private static String dtdLink(String name) {
		return "<!DOCTYPE " + name + " SYSTEM \"" + Constants.SERVER_ADDRESS
				+ name + ".dtd\">";
	}
	
}
